# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

add_custom_target(ecmascript_checked_tests COMMENT "Running ecmascript tests with checkers")
add_dependencies(ecmascript_checked_tests ark)

function(panda_add_checked_test_ecma)
    set(prefix ARG)
    set(singleValues NAME FILE SUPPORT_RELEASE LIBCORE)
    set(multiValues AUX_FILES EXT_FILES)
    cmake_parse_arguments(${prefix} "" "${singleValues}" "${multiValues}" ${ARGN})

    # Events does not work in Release mode
    if (NOT DEFINED ARG_SUPPORT_RELEASE AND "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
        return()
    endif()

    if ("${ARG_NAME}" STREQUAL "")
        get_filename_component(TEST_NAME "${ARG_FILE}" NAME_WE)
        set(TEST_NAME "${TEST_NAME}.checked")
    else()
        set(TEST_NAME "${ARG_NAME}.checked")
    endif()
    set(CHECKER "${PANDA_ROOT}/tests/checked/checker.rb")
    set(TEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}")
    set(BINARY_FILE "${TEST_DIR}/test.abc")
    set(BUILD_LOG   "${TEST_DIR}/build.log")

    if (NOT DEFINED ARG_FILE)
        message(FATAL_ERROR "Mandatory FILE argument is not defined.")
    endif()

    file(MAKE_DIRECTORY "${TEST_DIR}")

    compile_file_ecma(FILE ${ARG_FILE} OUTPUT_FILE ${BINARY_FILE} WORKING_DIR ${TEST_DIR})

    set(EXT_FILES "")
    foreach(APP_FILE ${ARG_EXT_FILES})
        get_filename_component(APP_FILE_BASE "${APP_FILE}" NAME_WE)
        set(APP_FILE_OUTPUT "${TEST_DIR}/${APP_FILE_BASE}.abc")
        compile_file_ecma(FILE ${APP_FILE} OUTPUT_FILE "${APP_FILE_OUTPUT}" WORKING_DIR ${TEST_DIR})
        # TODO(msherstennikov): pass external files via --app-panda-files (now it doesn't work)
        list(APPEND stdlibs "${APP_FILE_OUTPUT}")
        list(APPEND EXT_FILES "${APP_FILE_OUTPUT}")
    endforeach()

    get_filename_component(TEST_TYPE "${ARG_FILE}" EXT)
    if (${TEST_TYPE} MATCHES "js")
        set(COMMAND_TOKEN "//!")
    else()
        set(COMMAND_TOKEN "#!")
    endif()

    set(OPTIONS "--load-runtimes=ecmascript" "--run-gc-in-place")

    if (NOT PANDA_CI_TESTING_MODE STREQUAL "Nightly")
        set (OPTIONS ${OPTIONS} "--compiler-check-final=true")
    endif()

    if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
        set(RELEASE_OPT "--release")
    endif()

    # Run checker
    add_custom_target(${TEST_NAME}
                      COMMAND ${CHECKER} --source ${ARG_FILE}
                                         --panda $<TARGET_FILE:ark>
                                         --paoc $<TARGET_FILE:ark_aot>
                                         --run-prefix \"${PANDA_RUN_PREFIX}\"
                                         --test-file ${BINARY_FILE}
                                         --panda-options \"${OPTIONS}\"
                                         --paoc-options \"${OPTIONS}\"
                                         --command-token \"${COMMAND_TOKEN}\"
                                         ${RELEASE_OPT}
                      WORKING_DIRECTORY ${TEST_DIR}
                      COMMENT "Running ${TEST_NAME} checked test"
                      DEPENDS ${BINARY_FILE} ${EXT_FILES})

    add_dependencies(ecmascript_checked_tests ${TEST_NAME})

    foreach(AUX_FILE ${ARG_AUX_FILES})
        get_filename_component(AUX_NAME "${AUX_FILE}" NAME_WE)
        set(AUX_NAME "${AUX_NAME}.checked")
        add_dependencies(${TEST_NAME} ${AUX_NAME})
    endforeach()

endfunction()

if (NOT PANDA_TARGET_ARM32)
    # Disable checked tests with sanitizers for arm64, since it takes too long time running.
    if (PANDA_TARGET_AMD64 OR NOT PANDA_ARM64_TESTS_WITH_SANITIZER)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/inline_intrinsics.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/getunmappedargs_test.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/global_var.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/try_load_global_by_name.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_profiling.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/recompile_not_smi.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/recompile_double_with_int.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/recompile_not_number.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/recompile_undefined.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/destroy_method.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/recompile_special.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/donot_recompile_not_profiled.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/obj_by_index.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/obj_by_name.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/obj_by_value.js SUPPORT_RELEASE true)
        if (PANDA_WITH_ETS)
            panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inline_builtins_intrinsic_double_with_int.js SUPPORT_RELEASE true)
            panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inline_builtins_intrinsic_int_with_double.js SUPPORT_RELEASE true)
        endif()
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inline_builtins_instruction_int_with_double.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inline_builtins_instruction_double_with_int.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inline_builtins_speculation_fail.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_deoptimize.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_megamorphic.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_polymorphic.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_polymorphic_2.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_monomorphic_methods.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_monomorphic.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_static.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_call_profile_clear.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/peephole_negoverflowandzerocheck.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ldlex.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/typeof.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/string_equals.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/stlex.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/poplexenv.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/hclass_check_not_elim.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/hclass_check_elim.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/hclass_check_non_callable.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/hclass_check_constructor.js SUPPORT_RELEASE true)
        panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/load_from_constant_pool.js SUPPORT_RELEASE true)
        # Issue 27258
        # panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/acc_after_deopt.js SUPPORT_RELEASE true)

        # there is flaky bug when turning on TSAN
        if (NOT PANDA_ENABLE_THREAD_SANITIZER)
            panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/new_obj.js SUPPORT_RELEASE true)
            panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/new_obj_profiling.js SUPPORT_RELEASE true)
            panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_recursive_ctor_inlining.js SUPPORT_RELEASE true)
        endif()
    endif()
endif()
